/**
 * 
 */
package de.fsujena.chat_pi.ressources;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import javax.swing.tree.TreeNode;

import de.fsujena.chat_pi.ressources.User.ROLE;

/**
 * @author Erik Hebestreit
 *
 */
public class Room implements Serializable, TreeNode {
	/**
	 * 
	 */
	private static final long serialVersionUID = 6870041608857459221L;
	String name;
	public HashMap<String,TreeNode> users = new HashMap<String,TreeNode>();
	//public Room parent;
	//HashMap<String,Room> children = new HashMap<String,Room>();
	HashMap<String,User> whitelist = new HashMap<String,User>();			
	HashMap<String,User> blacklist = new HashMap<String,User>();	
	public List<String> directory =new ArrayList<String>();
	User owner;														//null if public room contains reference to owner if private
	boolean blackwhite;												//if true blacklist is used otherwise whitelist is used
	public  ROLE role;
	private TreeNode parent;
	private Vector<TreeNode> children=new Vector<TreeNode>();
	private int type;
	// Constants for types of node
    public static final int NODE_ROOM         = 0;
    public static final int NODE_USER     = 1;
    /**
	 * 
	 */
	public Room(String name,Room parent,int type,User owner) {
		// TODO Auto-generated constructor stub
		this.name=name;
		this.parent=parent;
		this.blackwhite=true;
		this.role=ROLE.STANDARD;
		if (parent!=null){
			for(int i=0;i<parent.directory.size();i++){
		this.directory.add(parent.directory.get(i));
			}
		this.directory.add(this.name);
		}else{
			this.directory.clear();
			this.directory.add("Foyer");
		}
		this.type=type;	
		this.setOwner(owner);
	}
//	public Room(String name,Room parent, boolean blackwhite) {
//		// TODO Auto-generated constructor stub
//		this.name=name;
//		this.parent=parent;
//		this.blackwhite=blackwhite;
//		this.role=ROLE.STANDARD;
//		if (parent!=null){
//			this.directory=parent.directory;
//			this.directory.add(parent.name);
//			}else{
//				this.directory.clear();
//				this.directory.add("Foyer");
//			}
//		
//	}
	public Room(String name,Room parent, int type,ROLE role) {
		// TODO Auto-generated constructor stub
		this.name=name;
		this.parent=parent;
		this.blackwhite=true;
		this.role=role;
		if (parent!=null){
			this.directory=parent.directory;
			this.directory.add(parent.name);
			}else{
				this.directory.clear();
				this.directory.add("Foyer");
			}
		this.type=type;	
	}

	
	public boolean createChild(String name,User owner){
		
		this.addChild(new Room(name,this,0,owner));
		return true;
	}
	
	public boolean deleteChild(String name){
		for(int i=0;i<children.size();i++){
			if(children.get(i).toString().equals(name)){
				children.remove(i);
			}
		}
		return true;
	}
	
	public TreeNode getChild(String name){
		for(int i=0;i<children.size();i++){
			if(children.get(i).toString().equals(name)){
				return children.get(i);
			}
		}
		return null;
	}
	public boolean childExists(String name){
		for(int i=0;i<children.size();i++){
			if((children.get(i).toString().equals(name))){
				return true;
			}
		}
		return false;
		}
	
	
	public User getUser(String name){
		return (User) users.get(name);
	}
	/**
	 * adds an user to the room
	 * @param user reference to the user
	 * @return 0 if successful
	 * @return 1 if user is blacklisted
	 * @return 2 if user is not on whitelist
	 * @return 3 if user has no mod rights
	 * @return 4 if user needs to be admin
	 * @return 5 some other error
	 */
	public int userentry(User user){
		switch (this.role){
		case STANDARD:
			if(user.role!=ROLE.ADMIN){
			if (blackwhite){
				if (blacklist.containsKey(user.name)){
					return 1;
				}else{
					users.put(user.name, user);
					children.add(user);
					//user.dir=this.directory;
					return 0;
				}
				
			}else{
				if (!whitelist.containsKey(user.name)){
					return 2;
				}else{
					users.put(user.name, user);
					children.add(user);
					//user.dir=this.directory;
					return 0;
				}
			}
			}else if(user.role==ROLE.ADMIN){
				users.put(user.name, user);
				children.add(user);
				//user.dir=this.directory;
				return 0;
			}
		case MODERATOR:
			if(user.role==ROLE.MODERATOR){
				if (blackwhite){
					if (blacklist.containsKey(user.name)){
						return 1;
					}else{
						users.put(user.name, user);
						children.add(user);
						//user.dir=this.directory;
						return 0;
					}
					
				}else{
					if (!whitelist.containsKey(user.name)){
						return 2;
					}else{
						users.put(user.name, user);
						children.add(user);
						//user.dir=this.directory;
						return 0;
					}
				}	
			}else if(user.role==ROLE.ADMIN){
				users.put(user.name, user);
				children.add(user);
				//user.dir=this.directory;
				return 0;
			}else {
				return 3;
			}
			
		case ADMIN:
			if(user.role==ROLE.ADMIN){
				users.put(user.name, user);
				children.add(user);
				//user.dir=this.directory;
				return 0;
			}else{
				return 4;
			}
		default:
			break;
		}
		return 5;
	}
	
	public void userExit(String name){
		users.remove(name);
		for(int i=0;i<children.size();i++){
			if(children.get(i).toString().equals(name)){
				children.removeElementAt(i);
			}
		}
	}
	public boolean addToWhitelist(User user){
		if (!whitelist.containsKey(user.name)){
			whitelist.put(user.name, user);
			return true;
		}else{
		return false;
	
		}
	}
	public boolean addToWhitelist(String name){
		if (!whitelist.containsKey(name)){
			whitelist.put(name, new User(name,""));
			return true;
		}else{
		return false;
	
		}
	}
	public boolean addToBlacklist(User user){
		if (!blacklist.containsKey(user.name)){
			blacklist.put(user.name, user);
			return true;
		}else{
		return false;
	
		}
	}
	public boolean addToBlacklist(String name){
		if (!blacklist.containsKey(name)){
			blacklist.put(name, new User(name,""));
			return true;
		}else{
		return false;
	
		}
	}
	public boolean removeFromWhitelist(String name){
		if (whitelist.containsKey(name)){
			whitelist.remove(name);
			return true;
		}else{
		return false;
		}
	}
	public boolean removeFromBlacklist(String name){
		if (blacklist.containsKey(name)){
			blacklist.remove(name);
			return true;
		}else{
		return false;
		}
	}
	public List<String> getChildren(){
		List<String> names=new ArrayList<String>();
//		for(String temp:children.keySet()){
//			names.add(temp);
//		}
		for(int i=0;i<children.size();i++){
			names.add(children.get(i).toString());
		}
		
		return names;
	}
	public String[] getWhitelist(){
		String[] names=new String[whitelist.size()];
		int i=0;
		for(String temp:whitelist.keySet()){
			names[i]=temp;
			i++;
		}
		return names;
	}
	public String[] getBlacklist(){
		String[] names=new String[blacklist.size()];
		int i=0;
		for(String temp:blacklist.keySet()){
			names[i]=temp;
		i++;
		}
		return names;
	}
	public String getName(){
		return this.name;
	}
	/*public Room getParent(){
		if(parent!=null){
			return this.parent;
		}else{
			return null;
		}
	}*/
	
	public void changeMode(boolean mode){
		this.blackwhite=mode;
	}
	public boolean getMode(){
		return this.blackwhite;
	}
	public boolean userExists(String name){
		if(users.containsKey(name)){
			return true;
		}else{
			return false;
		}
	}
	public boolean setOwner(User user){
		this.owner=user;
		if (owner!=null){
			if(this.hasChildrooms()){
				return false;
			}
			this.owner=user;
			this.blackwhite=false;
			this.blacklist.clear();
			this.addToWhitelist(user);
			for(int i=0;i<children.size();i++){
				if((children.get(i) instanceof User)&&(!children.get(i).toString().equals(user.name))){
					this.addToWhitelist((User)children.get(i));
				}
			}
		}else{
			this.owner=null;
			this.blackwhite=true;
			this.whitelist.clear();
		}
		return true;
	}
	public User getOwner(){
	return this.owner;
	}
	public Set<String> userKeySet(){
		return this.users.keySet();
	}
	public List<String> getDir(){
		return this.directory;
	}
	
	public void clearUserlist(){
		if(users!=null){
			users.clear();
		}
		for(int i=0;i<children.size();i++){
			if(children.get(i) instanceof User){
				children.removeElementAt(i);
			}
		}
//		for(String name: users.keySet()){
//			this.userExit(name);
//		}
		
	}
	public void changeName(String newName){
		//String oldName=this.name;
		this.directory=null;
		this.directory=((Room)(this.parent)).getDir();
		this.directory.add(newName);
		this.name=newName;
		for(int i=0; i<children.size();i++){
			if(children.get(i) instanceof Room){
				((Room)children.get(i)).changeName(children.get(i).toString());
			}else if(children.get(i)instanceof User){
				((User)children.get(i)).dir=this.directory;
				((User)users.get(children.get(i).toString())).dir=this.directory;
			}
		}
		
	}
	
   
 
   
    public void addChild(TreeNode child) {
        children.add(child);
    }
   
    public void setParent(TreeNode parent) {
        this.parent = parent;
    }
   
    @Override
    public Enumeration<TreeNode> children() {
        return children.elements();
    }

    @Override
    public boolean getAllowsChildren() {
        return true;
    }

    @Override
    public TreeNode getChildAt(int childIndex) {
        return children.elementAt(childIndex);
    }

    @Override
    public int getChildCount() {
    	return children.size();
    }

    @Override
    public int getIndex(TreeNode node) {
        return children.indexOf(node);
    }

    @Override
    public TreeNode getParent() {
        return this.parent;
    }

    @Override
    public boolean isLeaf() {
        return false;
    }

    public void setTitle(String title) {
        this.name = title;
    }

    public String getTitle() {
        return name;
    }
   
    /**
     * The node object should override this method to provide a text that will
     * be displayed for the node in the tree.
     */
    public String toString() {
        return name;
    }

    public int getType() {
        return type;
    }   
    
    public Room copyRoom(){
    	Room temp=new Room(this.toString(),(Room) this.getParent(),0,this.getOwner());
    	temp.users.clear();
    	
    	for(String name: this.users.keySet()){
    	temp.users.put(name, this.users.get(name));	
    	}
    	
    	for(int i=0;i<this.getChildCount();i++){
    	if(this.getChildAt(i) instanceof Room){
    		temp.addChild(((Room)(this.getChildAt(i))).copyRoom());
    	}else if(this.getChildAt(i) instanceof User){
    		temp.addChild(this.getChildAt(i));
    	}
    	
    }
    	temp.setOwner(this.getOwner());
    	for(String name: this.whitelist.keySet()){
    		temp.addToWhitelist(name);
    	}
    	
    	for(String name: this.blacklist.keySet()){
    		temp.addToBlacklist(name);
    	}
    	temp.blackwhite=this.blackwhite;
    return temp;
    }
    
    public void setType(int type){
    	this.type=type;
    }
    public boolean hasChildrooms(){
    	for(int i=0;i<children.size();i++){
    		if(children.get(i) instanceof Room){
    			return true;
    		}
    	}
    return false;
    }
  
}
